<?php
declare(strict_types=1);

namespace App\Service;

use App\Components\Mail;
use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Model\EmailCode;
use App\Model\User;
use App\Service\Service;
use Hyperf\Context\ApplicationContext;
use function PHPUnit\Framework\throwException;

class MailService extends Service
{
    /** 通过邮件获取验证码
     * @param $email
     * @return mixed
     */
    public function getCode($email)
    {
        //限制频率，5分钟3次
        $time = time();
        $sendNum = EmailCode::query()
            ->where('email', $email)
            ->where('create_time', '>', $time - 300)
            ->count();
        if ($sendNum > 3) {
            throwException(new BusinessException(ErrorCode::CODE_SENT_FREQUENTILY));
        }
        //判断邮箱用户是否已存在
        $user = User::query()->where('email', $email)->first();
        if (!empty($user)) {
            throw new BusinessException(ErrorCode::USER_EXISTS);
        }
        //生成并保存验证码
        $code = random_int(1000, 9999);
        $emailCode = new EmailCode();
        $emailCode->email = $email;
        $emailCode->code = $code;
        $emailCode->save();
        //发送验证码
        try {
            \Hyperf\Coroutine\co(function () use ($email, $code) {
                $mail = ApplicationContext::getContainer()->get(Mail::class);
                $mail->to($email)->send('账号激活', '您的验证码是： <b style="color: #f40303;">' . $code . '</b>');
            });
        } catch (\Exception $e) {
            throw new BusinessException(ErrorCode::MAIL_SEND_FAILD);
        }
        return true;
    }

    /**
     * 校验验证码
     * @param $email
     * @param $code
     * @return bool
     */
    public function verifyCode($email, $code)
    {
        if (empty($email) || empty($code)) {
            throw new BusinessException(ErrorCode::CODE_ERROR);
        }
        $result = EmailCode::query()
            ->where(['email' => $email, 'code' => $code])
            ->orderBy('id', 'desc')
            ->first();
        if (empty($result)) {
            throw new BusinessException(ErrorCode::CODE_ERROR);
        }
        $now = time();
        if ($result['create_time'] < $now-300) {
            throw new BusinessException(ErrorCode::CODE_EXPIRED);
        }
        return true;
    }

}